@bendyline/squisq-editor-react 1.2.2 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/EditorContext.d.ts +65 -1
- package/dist/EditorContext.d.ts.map +1 -1
- package/dist/EditorContext.js +31 -4
- package/dist/EditorContext.js.map +1 -1
- package/dist/EditorShell.d.ts +112 -2
- package/dist/EditorShell.d.ts.map +1 -1
- package/dist/EditorShell.js +95 -11
- package/dist/EditorShell.js.map +1 -1
- package/dist/ImageNodeView.d.ts.map +1 -1
- package/dist/ImageNodeView.js +12 -2
- package/dist/ImageNodeView.js.map +1 -1
- package/dist/MediaBin.d.ts +12 -1
- package/dist/MediaBin.d.ts.map +1 -1
- package/dist/MediaBin.js +29 -4
- package/dist/MediaBin.js.map +1 -1
- package/dist/MentionExtension.d.ts +22 -0
- package/dist/MentionExtension.d.ts.map +1 -0
- package/dist/MentionExtension.js +242 -0
- package/dist/MentionExtension.js.map +1 -0
- package/dist/RawEditor.d.ts +8 -1
- package/dist/RawEditor.d.ts.map +1 -1
- package/dist/RawEditor.js +167 -30
- package/dist/RawEditor.js.map +1 -1
- package/dist/TemplateAnnotation.d.ts.map +1 -1
- package/dist/TemplateAnnotation.js +4 -2
- package/dist/TemplateAnnotation.js.map +1 -1
- package/dist/Toolbar.d.ts +7 -1
- package/dist/Toolbar.d.ts.map +1 -1
- package/dist/Toolbar.js +57 -18
- package/dist/Toolbar.js.map +1 -1
- package/dist/Tooltip.d.ts +10 -0
- package/dist/Tooltip.d.ts.map +1 -0
- package/dist/Tooltip.js +104 -0
- package/dist/Tooltip.js.map +1 -0
- package/dist/ViewSwitcher.d.ts +1 -1
- package/dist/ViewSwitcher.d.ts.map +1 -1
- package/dist/ViewSwitcher.js +10 -4
- package/dist/ViewSwitcher.js.map +1 -1
- package/dist/WysiwygEditor.d.ts +13 -2
- package/dist/WysiwygEditor.d.ts.map +1 -1
- package/dist/WysiwygEditor.js +239 -4
- package/dist/WysiwygEditor.js.map +1 -1
- package/dist/__tests__/detectMarkdown.test.d.ts +2 -0
- package/dist/__tests__/detectMarkdown.test.d.ts.map +1 -0
- package/dist/__tests__/detectMarkdown.test.js +69 -0
- package/dist/__tests__/detectMarkdown.test.js.map +1 -0
- package/dist/__tests__/fileKind.test.d.ts +2 -0
- package/dist/__tests__/fileKind.test.d.ts.map +1 -0
- package/dist/__tests__/fileKind.test.js +81 -0
- package/dist/__tests__/fileKind.test.js.map +1 -0
- package/dist/__tests__/mediaAttachmentFlow.test.d.ts +2 -0
- package/dist/__tests__/mediaAttachmentFlow.test.d.ts.map +1 -0
- package/dist/__tests__/mediaAttachmentFlow.test.js +99 -0
- package/dist/__tests__/mediaAttachmentFlow.test.js.map +1 -0
- package/dist/__tests__/tiptapBridge.test.js +49 -0
- package/dist/__tests__/tiptapBridge.test.js.map +1 -1
- package/dist/__tests__/tiptapImageRoundTrip.test.d.ts +2 -0
- package/dist/__tests__/tiptapImageRoundTrip.test.d.ts.map +1 -0
- package/dist/__tests__/tiptapImageRoundTrip.test.js +68 -0
- package/dist/__tests__/tiptapImageRoundTrip.test.js.map +1 -0
- package/dist/detectMarkdown.d.ts +20 -0
- package/dist/detectMarkdown.d.ts.map +1 -0
- package/dist/detectMarkdown.js +61 -0
- package/dist/detectMarkdown.js.map +1 -0
- package/dist/fileKind.d.ts +30 -0
- package/dist/fileKind.d.ts.map +1 -0
- package/dist/fileKind.js +123 -0
- package/dist/fileKind.js.map +1 -0
- package/dist/hooks/useFileDrop.d.ts.map +1 -1
- package/dist/hooks/useFileDrop.js +9 -7
- package/dist/hooks/useFileDrop.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/mediaDragMime.d.ts +17 -0
- package/dist/mediaDragMime.d.ts.map +1 -0
- package/dist/mediaDragMime.js +22 -0
- package/dist/mediaDragMime.js.map +1 -0
- package/dist/tiptapBridge.d.ts.map +1 -1
- package/dist/tiptapBridge.js +99 -6
- package/dist/tiptapBridge.js.map +1 -1
- package/package.json +9 -7
- package/src/EditorContext.tsx +106 -3
- package/src/EditorShell.tsx +313 -21
- package/src/ImageNodeView.tsx +15 -2
- package/src/MediaBin.tsx +45 -4
- package/src/MentionExtension.tsx +258 -0
- package/src/RawEditor.tsx +193 -37
- package/src/TemplateAnnotation.ts +4 -2
- package/src/Toolbar.tsx +111 -48
- package/src/Tooltip.tsx +124 -0
- package/src/ViewSwitcher.tsx +15 -5
- package/src/WysiwygEditor.tsx +270 -5
- package/src/__tests__/detectMarkdown.test.ts +88 -0
- package/src/__tests__/fileKind.test.ts +96 -0
- package/src/__tests__/mediaAttachmentFlow.test.ts +110 -0
- package/src/__tests__/tiptapBridge.test.ts +58 -0
- package/src/__tests__/tiptapImageRoundTrip.test.ts +73 -0
- package/src/detectMarkdown.ts +62 -0
- package/src/fileKind.ts +134 -0
- package/src/hooks/useFileDrop.ts +10 -6
- package/src/index.ts +11 -0
- package/src/mediaDragMime.ts +32 -0
- package/src/styles/editor.css +214 -8
- package/src/tiptapBridge.ts +107 -6
package/dist/EditorContext.d.ts
CHANGED
|
@@ -13,8 +13,38 @@ import type { Editor as TiptapEditor } from '@tiptap/core';
|
|
|
13
13
|
import type { editor as MonacoEditorNs } from 'monaco-editor';
|
|
14
14
|
/** Monaco standalone code editor instance type */
|
|
15
15
|
type MonacoEditor = MonacoEditorNs.IStandaloneCodeEditor;
|
|
16
|
+
/**
|
|
17
|
+
* One candidate returned by a {@link MentionProvider}. Shown in the editor's
|
|
18
|
+
* `@` popover. `id` is the stable identifier (serialized into the mention
|
|
19
|
+
* wire format); `label` is what the reader sees; `scheme` is the namespace
|
|
20
|
+
* (e.g. `'user'`, `'issue'`) written into the markdown as `@[label](scheme:id)`;
|
|
21
|
+
* `description` and `group` are optional hints for richer suggestion UIs.
|
|
22
|
+
*
|
|
23
|
+
* Different candidates in the same result set may carry different schemes —
|
|
24
|
+
* a provider that returns both users and issues, for example, tags each
|
|
25
|
+
* candidate with its own namespace and the editor emits mentions accordingly.
|
|
26
|
+
*/
|
|
27
|
+
export interface MentionCandidate {
|
|
28
|
+
id: string;
|
|
29
|
+
label: string;
|
|
30
|
+
scheme: string;
|
|
31
|
+
description?: string;
|
|
32
|
+
group?: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Looks up mention candidates matching a query. Called as the user types
|
|
36
|
+
* after `@`. The provider is free to do server-side or client-side filtering;
|
|
37
|
+
* the editor only cares that candidates come back in relevance order.
|
|
38
|
+
*/
|
|
39
|
+
export type MentionProvider = (query: string) => Promise<MentionCandidate[]>;
|
|
16
40
|
export type EditorView = 'raw' | 'wysiwyg' | 'preview';
|
|
17
41
|
export type EditorTheme = 'light' | 'dark';
|
|
42
|
+
/**
|
|
43
|
+
* Editor operating mode. `markdown` is the full experience (WYSIWYG +
|
|
44
|
+
* Preview tabs, formatting toolbar). `code` is a Monaco-only view used
|
|
45
|
+
* when the content represents a non-markdown file like `foo.ts`.
|
|
46
|
+
*/
|
|
47
|
+
export type EditorMode = 'markdown' | 'code';
|
|
18
48
|
export interface EditorState {
|
|
19
49
|
/** Raw markdown source string */
|
|
20
50
|
markdownSource: string;
|
|
@@ -30,6 +60,10 @@ export interface EditorState {
|
|
|
30
60
|
isParsing: boolean;
|
|
31
61
|
/** Current color theme */
|
|
32
62
|
theme: EditorTheme;
|
|
63
|
+
/** Operating mode — 'markdown' for the full shell, 'code' for Monaco-only. */
|
|
64
|
+
editorMode: EditorMode;
|
|
65
|
+
/** Monaco language ID for the Raw editor. */
|
|
66
|
+
language: string;
|
|
33
67
|
}
|
|
34
68
|
export interface EditorActions {
|
|
35
69
|
/** Set markdown source and trigger re-parse */
|
|
@@ -56,7 +90,23 @@ export interface EditorContextValue extends EditorState, EditorActions {
|
|
|
56
90
|
monacoEditor: MonacoEditor | null;
|
|
57
91
|
/** MediaProvider for resolving image URLs in the WYSIWYG editor */
|
|
58
92
|
mediaProvider: MediaProvider | null;
|
|
93
|
+
/**
|
|
94
|
+
* How pasted/inserted images should be displayed in the WYSIWYG view.
|
|
95
|
+
* `'inline'` (default) lets them flow at natural size up to the editor
|
|
96
|
+
* width; `'thumbnail'` constrains them to a 100×100 box so chat
|
|
97
|
+
* composers and other dense surfaces don't get dominated by a single
|
|
98
|
+
* pasted screenshot. The stored image bytes are unchanged — this is a
|
|
99
|
+
* pure render-time decision.
|
|
100
|
+
*/
|
|
101
|
+
imageDisplayMode: ImageDisplayMode;
|
|
102
|
+
/**
|
|
103
|
+
* Optional provider for `@`-mention suggestions. When set, both the
|
|
104
|
+
* WYSIWYG (Tiptap) and Raw (Monaco) editors show a mention popover as
|
|
105
|
+
* the user types `@<query>`. When unset, `@` is just a literal character.
|
|
106
|
+
*/
|
|
107
|
+
mentionProvider: MentionProvider | null;
|
|
59
108
|
}
|
|
109
|
+
export type ImageDisplayMode = 'inline' | 'thumbnail';
|
|
60
110
|
/**
|
|
61
111
|
* Hook to access the editor context. Must be used within an EditorProvider.
|
|
62
112
|
*/
|
|
@@ -72,12 +122,26 @@ export interface EditorProviderProps {
|
|
|
72
122
|
theme?: EditorTheme;
|
|
73
123
|
/** MediaProvider for resolving image URLs */
|
|
74
124
|
mediaProvider?: MediaProvider | null;
|
|
125
|
+
/** Display mode for images in the WYSIWYG view. Defaults to `'inline'`. */
|
|
126
|
+
imageDisplayMode?: ImageDisplayMode;
|
|
127
|
+
/**
|
|
128
|
+
* Async provider for `@`-mention suggestions. Omit to disable mentions
|
|
129
|
+
* entirely — typing `@` becomes just a literal character again.
|
|
130
|
+
*/
|
|
131
|
+
mentionProvider?: MentionProvider | null;
|
|
132
|
+
/**
|
|
133
|
+
* File name (e.g. `foo.ts`) or bare extension — used to pick a Monaco
|
|
134
|
+
* language and decide between markdown vs. code mode.
|
|
135
|
+
*/
|
|
136
|
+
fileName?: string;
|
|
137
|
+
/** Explicit Monaco language ID — wins over the fileName-derived one. */
|
|
138
|
+
language?: string;
|
|
75
139
|
children: ReactNode;
|
|
76
140
|
}
|
|
77
141
|
/**
|
|
78
142
|
* Provides shared editor state to all child components.
|
|
79
143
|
* Automatically parses markdown and generates a Doc whenever the source changes.
|
|
80
144
|
*/
|
|
81
|
-
export declare function EditorProvider({ initialMarkdown, initialView, articleId, theme: initialTheme, mediaProvider, children, }: EditorProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
145
|
+
export declare function EditorProvider({ initialMarkdown, initialView, articleId, theme: initialTheme, mediaProvider, imageDisplayMode, mentionProvider, fileName, language, children, }: EditorProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
82
146
|
export {};
|
|
83
147
|
//# sourceMappingURL=EditorContext.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EditorContext.d.ts","sourceRoot":"","sources":["../src/EditorContext.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAQL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAGnE,OAAO,KAAK,EAAE,MAAM,IAAI,YAAY,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,KAAK,EAAE,MAAM,IAAI,cAAc,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"EditorContext.d.ts","sourceRoot":"","sources":["../src/EditorContext.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAQL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAGnE,OAAO,KAAK,EAAE,MAAM,IAAI,YAAY,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,KAAK,EAAE,MAAM,IAAI,cAAc,EAAE,MAAM,eAAe,CAAC;AAI9D,kDAAkD;AAClD,KAAK,YAAY,GAAG,cAAc,CAAC,qBAAqB,CAAC;AAEzD;;;;;;;;;;GAUG;AACH,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC;AAI7E,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,SAAS,GAAG,SAAS,CAAC;AACvD,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,MAAM,CAAC;AAC3C;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,MAAM,CAAC;AAE7C,MAAM,WAAW,WAAW;IAC1B,iCAAiC;IACjC,cAAc,EAAE,MAAM,CAAC;IACvB,0CAA0C;IAC1C,WAAW,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACrC,sCAAsC;IACtC,GAAG,EAAE,GAAG,GAAG,IAAI,CAAC;IAChB,mCAAmC;IACnC,UAAU,EAAE,UAAU,CAAC;IACvB,0BAA0B;IAC1B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,iCAAiC;IACjC,SAAS,EAAE,OAAO,CAAC;IACnB,0BAA0B;IAC1B,KAAK,EAAE,WAAW,CAAC;IACnB,8EAA8E;IAC9E,UAAU,EAAE,UAAU,CAAC;IACvB,6CAA6C;IAC7C,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,+CAA+C;IAC/C,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,+DAA+D;IAC/D,cAAc,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAChD,6BAA6B;IAC7B,aAAa,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;IAC1C,iFAAiF;IACjF,eAAe,EAAE,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,KAAK,IAAI,CAAC;IACvD,6EAA6E;IAC7E,eAAe,EAAE,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,KAAK,IAAI,CAAC;IACvD,0BAA0B;IAC1B,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IACvC,sEAAsE;IACtE,cAAc,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,qDAAqD;IACrD,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC;AAED,MAAM,WAAW,kBAAmB,SAAQ,WAAW,EAAE,aAAa;IACpE,yEAAyE;IACzE,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;IAClC,qEAAqE;IACrE,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;IAClC,mEAAmE;IACnE,aAAa,EAAE,aAAa,GAAG,IAAI,CAAC;IACpC;;;;;;;OAOG;IACH,gBAAgB,EAAE,gBAAgB,CAAC;IACnC;;;;OAIG;IACH,eAAe,EAAE,eAAe,GAAG,IAAI,CAAC;CACzC;AAED,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,WAAW,CAAC;AAMtD;;GAEG;AAEH,wBAAgB,gBAAgB,IAAI,kBAAkB,CAMrD;AAID,MAAM,WAAW,mBAAmB;IAClC,+BAA+B;IAC/B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,0BAA0B;IAC1B,WAAW,CAAC,EAAE,UAAU,CAAC;IACzB,8CAA8C;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kBAAkB;IAClB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,6CAA6C;IAC7C,aAAa,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IACrC,2EAA2E;IAC3E,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC;;;OAGG;IACH,eAAe,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IACzC;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,EAC7B,eAAoB,EACpB,WAAmB,EACnB,SAAsB,EACtB,KAAK,EAAE,YAAsB,EAC7B,aAAoB,EACpB,gBAA2B,EAC3B,eAAsB,EACtB,QAAQ,EACR,QAAQ,EACR,QAAQ,GACT,EAAE,mBAAmB,2CA6NrB"}
|
package/dist/EditorContext.js
CHANGED
|
@@ -11,6 +11,7 @@ import { createContext, useContext, useState, useCallback, useMemo, useRef, useE
|
|
|
11
11
|
import { parseMarkdown, stringifyMarkdown } from '@bendyline/squisq/markdown';
|
|
12
12
|
import { markdownToDoc } from '@bendyline/squisq/doc';
|
|
13
13
|
import { markdownToTiptap } from './tiptapBridge';
|
|
14
|
+
import { resolveFileKind } from './fileKind';
|
|
14
15
|
// ─── Context ─────────────────────────────────────────────
|
|
15
16
|
const EditorContext = createContext(null);
|
|
16
17
|
/**
|
|
@@ -28,11 +29,22 @@ export function useEditorContext() {
|
|
|
28
29
|
* Provides shared editor state to all child components.
|
|
29
30
|
* Automatically parses markdown and generates a Doc whenever the source changes.
|
|
30
31
|
*/
|
|
31
|
-
export function EditorProvider({ initialMarkdown = '', initialView = 'raw', articleId = 'untitled', theme: initialTheme = 'light', mediaProvider = null, children, }) {
|
|
32
|
+
export function EditorProvider({ initialMarkdown = '', initialView = 'raw', articleId = 'untitled', theme: initialTheme = 'light', mediaProvider = null, imageDisplayMode = 'inline', mentionProvider = null, fileName, language, children, }) {
|
|
33
|
+
// Resolve once per provider mount. Changing fileName/language after mount
|
|
34
|
+
// would require recreating the Monaco model anyway, so treat it as static.
|
|
35
|
+
const { mode: editorMode, language: resolvedLanguage } = useMemo(() => resolveFileKind(fileName, language), [fileName, language]);
|
|
36
|
+
// In code mode, WYSIWYG and Preview aren't rendered — force the starting
|
|
37
|
+
// view to 'raw' so we don't boot into an unmounted surface.
|
|
32
38
|
const [markdownSource, setMarkdownSourceRaw] = useState(initialMarkdown);
|
|
33
39
|
const [markdownDoc, setMarkdownDocState] = useState(null);
|
|
34
40
|
const [doc, setDoc] = useState(null);
|
|
35
|
-
const [activeView,
|
|
41
|
+
const [activeView, setActiveViewRaw] = useState(editorMode === 'code' ? 'raw' : initialView);
|
|
42
|
+
const setActiveView = useCallback((view) => {
|
|
43
|
+
// In code mode only the raw view is valid; ignore any other requests.
|
|
44
|
+
if (editorMode === 'code' && view !== 'raw')
|
|
45
|
+
return;
|
|
46
|
+
setActiveViewRaw(view);
|
|
47
|
+
}, [editorMode]);
|
|
36
48
|
const [parseError, setParseError] = useState(null);
|
|
37
49
|
const [isParsing, setIsParsing] = useState(false);
|
|
38
50
|
const [theme, setTheme] = useState(initialTheme);
|
|
@@ -74,8 +86,13 @@ export function EditorProvider({ initialMarkdown = '', initialView = 'raw', arti
|
|
|
74
86
|
setIsParsing(false);
|
|
75
87
|
}
|
|
76
88
|
}, []);
|
|
77
|
-
// Parse on source changes with debounce
|
|
89
|
+
// Parse on source changes with debounce. Skipped in code mode — the
|
|
90
|
+
// WYSIWYG/Preview surfaces that consume markdownDoc/doc aren't mounted,
|
|
91
|
+
// so there's nothing to feed and no reason to run the markdown parser on
|
|
92
|
+
// TypeScript / JSON / etc.
|
|
78
93
|
useEffect(() => {
|
|
94
|
+
if (editorMode === 'code')
|
|
95
|
+
return;
|
|
79
96
|
if (parseTimeoutRef.current) {
|
|
80
97
|
clearTimeout(parseTimeoutRef.current);
|
|
81
98
|
}
|
|
@@ -87,9 +104,11 @@ export function EditorProvider({ initialMarkdown = '', initialView = 'raw', arti
|
|
|
87
104
|
clearTimeout(parseTimeoutRef.current);
|
|
88
105
|
}
|
|
89
106
|
};
|
|
90
|
-
}, [markdownSource, doParse]);
|
|
107
|
+
}, [markdownSource, doParse, editorMode]);
|
|
91
108
|
// Initial parse
|
|
92
109
|
useEffect(() => {
|
|
110
|
+
if (editorMode === 'code')
|
|
111
|
+
return;
|
|
93
112
|
if (initialMarkdown) {
|
|
94
113
|
doParse(initialMarkdown);
|
|
95
114
|
}
|
|
@@ -170,9 +189,13 @@ export function EditorProvider({ initialMarkdown = '', initialView = 'raw', arti
|
|
|
170
189
|
parseError,
|
|
171
190
|
isParsing,
|
|
172
191
|
theme,
|
|
192
|
+
editorMode,
|
|
193
|
+
language: resolvedLanguage,
|
|
173
194
|
tiptapEditor,
|
|
174
195
|
monacoEditor,
|
|
175
196
|
mediaProvider,
|
|
197
|
+
imageDisplayMode,
|
|
198
|
+
mentionProvider,
|
|
176
199
|
setMarkdownSource,
|
|
177
200
|
setMarkdownDoc,
|
|
178
201
|
setActiveView,
|
|
@@ -189,9 +212,13 @@ export function EditorProvider({ initialMarkdown = '', initialView = 'raw', arti
|
|
|
189
212
|
parseError,
|
|
190
213
|
isParsing,
|
|
191
214
|
theme,
|
|
215
|
+
editorMode,
|
|
216
|
+
resolvedLanguage,
|
|
192
217
|
tiptapEditor,
|
|
193
218
|
monacoEditor,
|
|
194
219
|
mediaProvider,
|
|
220
|
+
imageDisplayMode,
|
|
221
|
+
mentionProvider,
|
|
195
222
|
setMarkdownSource,
|
|
196
223
|
setMarkdownDoc,
|
|
197
224
|
setActiveView,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EditorContext.js","sourceRoot":"","sources":["../src/EditorContext.tsx"],"names":[],"mappings":";AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,aAAa,EACb,UAAU,EACV,QAAQ,EACR,WAAW,EACX,OAAO,EACP,MAAM,EACN,SAAS,GAEV,MAAM,OAAO,CAAC;AAGf,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAGtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"EditorContext.js","sourceRoot":"","sources":["../src/EditorContext.tsx"],"names":[],"mappings":"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"}
|
package/dist/EditorShell.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* views, and StatusBar into a complete editing experience. Wraps everything
|
|
6
6
|
* in an EditorProvider for shared state.
|
|
7
7
|
*/
|
|
8
|
-
import { type EditorView } from './EditorContext';
|
|
8
|
+
import { type EditorView, type ImageDisplayMode, type MentionProvider } from './EditorContext';
|
|
9
9
|
import type { MediaProvider } from '@bendyline/squisq/schemas';
|
|
10
10
|
import type { ContentContainer } from '@bendyline/squisq/storage';
|
|
11
11
|
import type { ReactNode } from 'react';
|
|
@@ -28,6 +28,17 @@ export interface EditorShellProps {
|
|
|
28
28
|
className?: string;
|
|
29
29
|
/** CSS height for the shell container (default: '100vh') */
|
|
30
30
|
height?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Minimum CSS height for the shell. When either `minHeight` or
|
|
33
|
+
* `maxHeight` is set, the shell switches to **auto-grow mode**:
|
|
34
|
+
* `height` is ignored, the root becomes `height: auto` between the
|
|
35
|
+
* bounds, and the content area scrolls internally when content
|
|
36
|
+
* exceeds `maxHeight`. Useful for chat composers that should grow
|
|
37
|
+
* with content up to some cap.
|
|
38
|
+
*/
|
|
39
|
+
minHeight?: string;
|
|
40
|
+
/** See `minHeight`. Upper bound of the auto-grow range. */
|
|
41
|
+
maxHeight?: string;
|
|
31
42
|
/** Optional MediaProvider for the Files panel. When set (even to null), a Files toggle appears in the toolbar. */
|
|
32
43
|
mediaProvider?: MediaProvider | null;
|
|
33
44
|
/** Optional ContentContainer for audio mapping (MP3 discovery + timing.json reading). */
|
|
@@ -40,10 +51,109 @@ export interface EditorShellProps {
|
|
|
40
51
|
toolbarSlotAfterActions?: ReactNode;
|
|
41
52
|
/** Content rendered at the rightmost end of the toolbar, after all other elements. */
|
|
42
53
|
toolbarSlotRight?: ReactNode;
|
|
54
|
+
/**
|
|
55
|
+
* Whether to show the "Play" (preview) tab in the toolbar. When false, the
|
|
56
|
+
* tab and its preview panel are hidden, and ⌘3 becomes a no-op. Use this
|
|
57
|
+
* when embedding the editor somewhere the slideshow preview doesn't make
|
|
58
|
+
* sense (e.g. editing free-form prompt documents). Defaults to true.
|
|
59
|
+
*/
|
|
60
|
+
showPlayTab?: boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Optional "submit on Enter" callback. When provided, a plain Enter
|
|
63
|
+
* keypress fires this callback instead of inserting a newline, and
|
|
64
|
+
* Cmd/Ctrl+Enter inserts a newline instead. Matches chat-composer UX
|
|
65
|
+
* (Slack, Discord). When omitted, the editor behaves normally.
|
|
66
|
+
*/
|
|
67
|
+
submitOnEnter?: () => void;
|
|
68
|
+
/**
|
|
69
|
+
* Let the WYSIWYG editing surface fill its container instead of rendering
|
|
70
|
+
* as a centered 800px "page" column. Useful when embedding in chat
|
|
71
|
+
* composers, side panels, or any layout where the page metaphor doesn't
|
|
72
|
+
* fit. Defaults to false (page mode).
|
|
73
|
+
*/
|
|
74
|
+
fullWidth?: boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Font-family stack applied to the editor **chrome** — toolbar buttons,
|
|
77
|
+
* tabs, status bar, and control surfaces. The actual editing areas
|
|
78
|
+
* (Tiptap / Monaco) keep their own fonts so document editing isn't
|
|
79
|
+
* affected. Use this when the editor is embedded in a larger product
|
|
80
|
+
* that has its own UX type system and you want the controls to blend in.
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```tsx
|
|
84
|
+
* <EditorShell uxFont="'Hanken Grotesk', system-ui, sans-serif" ... />
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
uxFont?: string;
|
|
88
|
+
/**
|
|
89
|
+
* Drop the editor's generous page-style padding in favor of a tight
|
|
90
|
+
* layout that hugs its container. The default WYSIWYG surface uses
|
|
91
|
+
* 16×24px padding suitable for editing long-form documents; chat
|
|
92
|
+
* composers want much less. Applies to the editing area only — the
|
|
93
|
+
* toolbar, tabs, and status bar keep their normal sizing.
|
|
94
|
+
*/
|
|
95
|
+
thinMargins?: boolean;
|
|
96
|
+
/**
|
|
97
|
+
* Render the bottom status bar (word / character / line / block counts
|
|
98
|
+
* and parse-state indicator). Defaults to `true`. Set to `false` in
|
|
99
|
+
* embedded surfaces — chat composers and other short-form inputs —
|
|
100
|
+
* where the stats are noise.
|
|
101
|
+
*/
|
|
102
|
+
showStatusBar?: boolean;
|
|
103
|
+
/**
|
|
104
|
+
* How images should be displayed in the WYSIWYG view. `'inline'`
|
|
105
|
+
* (default) flows them at natural size up to the container width;
|
|
106
|
+
* `'thumbnail'` constrains each image to a 100×100 box with
|
|
107
|
+
* aspect-preserving containment — useful for chat composers and other
|
|
108
|
+
* dense surfaces where a full-resolution paste would dominate the
|
|
109
|
+
* layout. Storage bytes are unchanged either way.
|
|
110
|
+
*/
|
|
111
|
+
imageDisplayMode?: ImageDisplayMode;
|
|
112
|
+
/**
|
|
113
|
+
* File name (e.g. `foo.ts`) or bare extension that the content
|
|
114
|
+
* represents. When set to a non-markdown/text extension, the shell
|
|
115
|
+
* enters **code mode**: Monaco picks the right language based on the
|
|
116
|
+
* extension, the WYSIWYG and Preview tabs disappear, and the toolbar
|
|
117
|
+
* drops its markdown-specific formatting buttons. Markdown-ish
|
|
118
|
+
* extensions (`.md`, `.markdown`, `.mdown`, `.txt`) keep the full
|
|
119
|
+
* experience. Omit to get today's markdown behavior unchanged.
|
|
120
|
+
*/
|
|
121
|
+
fileName?: string;
|
|
122
|
+
/**
|
|
123
|
+
* Explicit Monaco language ID override (e.g. `'typescript'`,
|
|
124
|
+
* `'python'`, `'json'`). Wins over the language derived from
|
|
125
|
+
* `fileName`. Anything other than `'markdown'` or `'plaintext'`
|
|
126
|
+
* switches the shell into code mode.
|
|
127
|
+
*/
|
|
128
|
+
language?: string;
|
|
129
|
+
/**
|
|
130
|
+
* Optional async provider for `@`-mention suggestions. When supplied,
|
|
131
|
+
* typing `@` inside the editor opens a popover of candidates; selecting
|
|
132
|
+
* one inserts a `@[Label](scheme:id)` mention token. Used by chat
|
|
133
|
+
* composers and any other surface that wants to address named entities
|
|
134
|
+
* inline. Omit to disable mentions entirely.
|
|
135
|
+
*/
|
|
136
|
+
mentionProvider?: MentionProvider | null;
|
|
137
|
+
/**
|
|
138
|
+
* Placeholder text shown in the WYSIWYG editor while the document is
|
|
139
|
+
* empty. When omitted, the editor rotates through its own generic
|
|
140
|
+
* "start typing…" prompts; pass a value here to override with copy
|
|
141
|
+
* that fits the embedding surface (e.g. a chat composer knows who
|
|
142
|
+
* the message is going to and can say so).
|
|
143
|
+
*/
|
|
144
|
+
placeholder?: string;
|
|
145
|
+
/**
|
|
146
|
+
* When true, both editing surfaces become non-editable: Monaco runs in
|
|
147
|
+
* `readOnly` mode and Tiptap is set to `editable: false`. The toolbar
|
|
148
|
+
* still renders — hide it from the host side if you want a pure preview.
|
|
149
|
+
* Useful for reference panels that show file content without inviting
|
|
150
|
+
* accidental edits.
|
|
151
|
+
*/
|
|
152
|
+
readOnly?: boolean;
|
|
43
153
|
}
|
|
44
154
|
/**
|
|
45
155
|
* Complete markdown editor shell with toolbar, view switcher, and three
|
|
46
156
|
* editing modes: Raw (Monaco), WYSIWYG (Tiptap), and Preview.
|
|
47
157
|
*/
|
|
48
|
-
export declare function EditorShell({ initialMarkdown, initialView, articleId, basePath, onChange, theme, className, height, mediaProvider, container, showFilesToggle, toolbarSlotLeft, toolbarSlotAfterActions, toolbarSlotRight, }: EditorShellProps): import("react/jsx-runtime").JSX.Element;
|
|
158
|
+
export declare function EditorShell({ initialMarkdown, initialView, articleId, basePath, onChange, theme, className, height, minHeight, maxHeight, mediaProvider, container, showFilesToggle, toolbarSlotLeft, toolbarSlotAfterActions, toolbarSlotRight, showPlayTab, submitOnEnter, fullWidth, uxFont, thinMargins, showStatusBar, imageDisplayMode, fileName, language, mentionProvider, placeholder, readOnly, }: EditorShellProps): import("react/jsx-runtime").JSX.Element;
|
|
49
159
|
//# sourceMappingURL=EditorShell.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EditorShell.d.ts","sourceRoot":"","sources":["../src/EditorShell.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,
|
|
1
|
+
{"version":3,"file":"EditorShell.d.ts","sourceRoot":"","sources":["../src/EditorShell.tsx"],"names":[],"mappings":"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"}
|
package/dist/EditorShell.js
CHANGED
|
@@ -7,7 +7,7 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
7
7
|
* in an EditorProvider for shared state.
|
|
8
8
|
*/
|
|
9
9
|
import { useEffect, useState, useCallback } from 'react';
|
|
10
|
-
import { EditorProvider, useEditorContext } from './EditorContext';
|
|
10
|
+
import { EditorProvider, useEditorContext, } from './EditorContext';
|
|
11
11
|
import { Toolbar } from './Toolbar';
|
|
12
12
|
import { StatusBar } from './StatusBar';
|
|
13
13
|
import { RawEditor } from './RawEditor';
|
|
@@ -16,20 +16,25 @@ import { PreviewPanel } from './PreviewPanel';
|
|
|
16
16
|
import { PreviewSettingsProvider, PreviewToolbarControls } from './PreviewControls';
|
|
17
17
|
import { MediaBin } from './MediaBin';
|
|
18
18
|
import { DropZoneOverlay } from './DropZoneOverlay';
|
|
19
|
+
import { TooltipLayer } from './Tooltip';
|
|
19
20
|
import { useFileDrop } from './hooks/useFileDrop';
|
|
20
21
|
import { partitionFiles, processMediaFiles, processTextFile, processTextFiles, } from './utils/dropUtils';
|
|
21
22
|
/**
|
|
22
23
|
* Complete markdown editor shell with toolbar, view switcher, and three
|
|
23
24
|
* editing modes: Raw (Monaco), WYSIWYG (Tiptap), and Preview.
|
|
24
25
|
*/
|
|
25
|
-
export function EditorShell({ initialMarkdown = '', initialView = 'wysiwyg', articleId = 'untitled', basePath = '/', onChange, theme = 'light', className, height = '100vh', mediaProvider, container, showFilesToggle, toolbarSlotLeft, toolbarSlotAfterActions, toolbarSlotRight, }) {
|
|
26
|
+
export function EditorShell({ initialMarkdown = '', initialView = 'wysiwyg', articleId = 'untitled', basePath = '/', onChange, theme = 'light', className, height = '100vh', minHeight, maxHeight, mediaProvider, container, showFilesToggle, toolbarSlotLeft, toolbarSlotAfterActions, toolbarSlotRight, showPlayTab = true, submitOnEnter, fullWidth = false, uxFont, thinMargins = false, showStatusBar = true, imageDisplayMode = 'inline', fileName, language, mentionProvider, placeholder, readOnly = false, }) {
|
|
26
27
|
// Show the toggle when explicitly opted in, or when mediaProvider prop was passed at all
|
|
27
28
|
const filesToggleEnabled = showFilesToggle ?? mediaProvider !== undefined;
|
|
28
|
-
|
|
29
|
+
// If the host hides the Play tab but asked for it as the initial view,
|
|
30
|
+
// fall back to wysiwyg so we don't boot into a tab the user can't leave.
|
|
31
|
+
const effectiveInitialView = !showPlayTab && initialView === 'preview' ? 'wysiwyg' : initialView;
|
|
32
|
+
return (_jsx(EditorProvider, { initialMarkdown: initialMarkdown, initialView: effectiveInitialView, articleId: articleId, theme: theme, mediaProvider: mediaProvider, imageDisplayMode: imageDisplayMode, mentionProvider: mentionProvider, fileName: fileName, language: language, children: _jsx(EditorShellInner, { basePath: basePath, onChange: onChange, className: className, height: height, minHeight: minHeight, maxHeight: maxHeight, placeholder: placeholder, mediaProvider: mediaProvider ?? null, container: container, filesToggleEnabled: filesToggleEnabled, toolbarSlotLeft: toolbarSlotLeft, toolbarSlotAfterActions: toolbarSlotAfterActions, toolbarSlotRight: toolbarSlotRight, showPlayTab: showPlayTab, submitOnEnter: submitOnEnter, fullWidth: fullWidth, uxFont: uxFont, thinMargins: thinMargins, showStatusBar: showStatusBar, readOnly: readOnly }) }));
|
|
29
33
|
}
|
|
30
|
-
function EditorShellInner({ basePath, onChange, className, height, mediaProvider, container, filesToggleEnabled, toolbarSlotLeft, toolbarSlotAfterActions, toolbarSlotRight, }) {
|
|
31
|
-
const { activeView, markdownSource, doc, theme, insertAtCursor, replaceAll } = useEditorContext();
|
|
34
|
+
function EditorShellInner({ basePath, onChange, className, height, minHeight, maxHeight, placeholder, mediaProvider, container, filesToggleEnabled, toolbarSlotLeft, toolbarSlotAfterActions, toolbarSlotRight, showPlayTab, submitOnEnter, fullWidth, uxFont, thinMargins, showStatusBar, readOnly, }) {
|
|
35
|
+
const { activeView, markdownSource, doc, theme, editorMode, insertAtCursor, replaceAll, tiptapEditor, monacoEditor, setMarkdownSource, } = useEditorContext();
|
|
32
36
|
const isPreview = activeView === 'preview';
|
|
37
|
+
const isCodeMode = editorMode === 'code';
|
|
33
38
|
const [showFiles, setShowFiles] = useState(false);
|
|
34
39
|
const [mediaRefreshKey, setMediaRefreshKey] = useState(0);
|
|
35
40
|
const isDark = theme === 'dark';
|
|
@@ -37,16 +42,75 @@ function EditorShellInner({ basePath, onChange, className, height, mediaProvider
|
|
|
37
42
|
setShowFiles((prev) => !prev);
|
|
38
43
|
}, []);
|
|
39
44
|
// ── Drag-and-drop file handling ──
|
|
45
|
+
/**
|
|
46
|
+
* Insert an uploaded media file at the editor's current cursor.
|
|
47
|
+
*
|
|
48
|
+
* - In **WYSIWYG** mode, insert an actual tiptap image node via
|
|
49
|
+
* `setImage({src, alt})` (images) or a link mark (non-images).
|
|
50
|
+
* Going through `setImage` directly mirrors the Toolbar's image
|
|
51
|
+
* button and avoids the round-trip through `markdownToTiptap`
|
|
52
|
+
* that historically lost `<img>` tags to tag-strip passes.
|
|
53
|
+
* - In **raw (Monaco)** or **preview** mode, fall back to
|
|
54
|
+
* `insertAtCursor` which emits the markdown snippet.
|
|
55
|
+
*
|
|
56
|
+
* Without this, upload-via-MediaBin and upload-via-drop both
|
|
57
|
+
* added the file to the bin and nowhere else — the composer sent
|
|
58
|
+
* an empty body and the downstream gezel reported "nothing came
|
|
59
|
+
* through."
|
|
60
|
+
*/
|
|
61
|
+
const insertMediaRef = useCallback((relativePath, name, mimeType) => {
|
|
62
|
+
const alt = name.replace(/\.[^.]+$/, '').replace(/[-_]/g, ' ');
|
|
63
|
+
const isImage = mimeType.startsWith('image/');
|
|
64
|
+
const snippet = isImage ? `` : `[${alt}](${relativePath})`;
|
|
65
|
+
if (activeView === 'wysiwyg' && tiptapEditor) {
|
|
66
|
+
if (isImage) {
|
|
67
|
+
tiptapEditor.chain().focus().setImage({ src: relativePath, alt }).run();
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
tiptapEditor
|
|
71
|
+
.chain()
|
|
72
|
+
.focus()
|
|
73
|
+
.insertContent([
|
|
74
|
+
{
|
|
75
|
+
type: 'text',
|
|
76
|
+
marks: [{ type: 'link', attrs: { href: relativePath } }],
|
|
77
|
+
text: alt,
|
|
78
|
+
},
|
|
79
|
+
])
|
|
80
|
+
.run();
|
|
81
|
+
}
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (activeView === 'raw' && monacoEditor) {
|
|
85
|
+
insertAtCursor(snippet);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
// Preview mode — no interactive editor to insert into. Append
|
|
89
|
+
// to markdown source so the ref is still in the buffer.
|
|
90
|
+
setMarkdownSource(markdownSource ? `${markdownSource}\n\n${snippet}` : snippet);
|
|
91
|
+
}, [activeView, tiptapEditor, monacoEditor, insertAtCursor, markdownSource, setMarkdownSource]);
|
|
40
92
|
const handleFileDrop = useCallback(async (files, target) => {
|
|
41
93
|
try {
|
|
42
94
|
const { media, text } = partitionFiles(files);
|
|
43
95
|
// Process media files
|
|
44
96
|
if (media.length > 0 && mediaProvider) {
|
|
45
|
-
await processMediaFiles(media, mediaProvider);
|
|
97
|
+
const paths = await processMediaFiles(media, mediaProvider);
|
|
46
98
|
setMediaRefreshKey((k) => k + 1);
|
|
47
99
|
// Auto-open the media bin so the user sees the new files
|
|
48
100
|
if (!showFiles)
|
|
49
101
|
setShowFiles(true);
|
|
102
|
+
// Insert each uploaded file as a markdown ref at the cursor so
|
|
103
|
+
// the body actually contains the attachment. Without this the
|
|
104
|
+
// bin holds the file but the serialized markdown stays empty,
|
|
105
|
+
// and anything downstream (chat send, document save) sees no
|
|
106
|
+
// reference to the upload.
|
|
107
|
+
for (let i = 0; i < media.length; i++) {
|
|
108
|
+
const file = media[i];
|
|
109
|
+
const path = paths[i];
|
|
110
|
+
if (!file || !path)
|
|
111
|
+
continue;
|
|
112
|
+
insertMediaRef(path, file.name, file.type || 'application/octet-stream');
|
|
113
|
+
}
|
|
50
114
|
}
|
|
51
115
|
// Process text files
|
|
52
116
|
if (text.length > 0) {
|
|
@@ -65,7 +129,7 @@ function EditorShellInner({ basePath, onChange, className, height, mediaProvider
|
|
|
65
129
|
catch (err) {
|
|
66
130
|
console.error('Failed to process dropped files:', err instanceof Error ? err.message : err);
|
|
67
131
|
}
|
|
68
|
-
}, [mediaProvider, showFiles, replaceAll, insertAtCursor]);
|
|
132
|
+
}, [mediaProvider, showFiles, replaceAll, insertAtCursor, insertMediaRef]);
|
|
69
133
|
const { isDragging, dragContentType, containerProps, zoneProps } = useFileDrop({
|
|
70
134
|
onDrop: handleFileDrop,
|
|
71
135
|
});
|
|
@@ -87,6 +151,8 @@ function EditorShellInner({ basePath, onChange, className, height, mediaProvider
|
|
|
87
151
|
document.querySelector('[data-view="raw"]')?.click();
|
|
88
152
|
break;
|
|
89
153
|
case '3':
|
|
154
|
+
if (!showPlayTab)
|
|
155
|
+
return;
|
|
90
156
|
e.preventDefault();
|
|
91
157
|
document.querySelector('[data-view="preview"]')?.click();
|
|
92
158
|
break;
|
|
@@ -95,12 +161,30 @@ function EditorShellInner({ basePath, onChange, className, height, mediaProvider
|
|
|
95
161
|
};
|
|
96
162
|
window.addEventListener('keydown', handler);
|
|
97
163
|
return () => window.removeEventListener('keydown', handler);
|
|
98
|
-
}, []);
|
|
99
|
-
|
|
164
|
+
}, [showPlayTab]);
|
|
165
|
+
const autoGrow = minHeight !== undefined || maxHeight !== undefined;
|
|
166
|
+
return (_jsxs("div", { className: `squisq-editor-shell ${className || ''}`, "data-theme": theme, "data-full-width": fullWidth ? 'true' : undefined, "data-thin-margins": thinMargins ? 'true' : undefined, style: {
|
|
100
167
|
display: 'flex',
|
|
101
168
|
flexDirection: 'column',
|
|
102
|
-
height,
|
|
103
169
|
overflow: 'hidden',
|
|
104
|
-
|
|
170
|
+
...(autoGrow ? { minHeight, maxHeight } : { height }),
|
|
171
|
+
// When a consumer supplies a UX font stack, expose it to the
|
|
172
|
+
// editor CSS via this custom property. Chrome elements (toolbar,
|
|
173
|
+
// tabs, status bar) consume `--squisq-ux-font` as their
|
|
174
|
+
// `font-family`, falling back to the system stack when unset.
|
|
175
|
+
...(uxFont ? { '--squisq-ux-font': uxFont } : {}),
|
|
176
|
+
}, ...containerProps, children: [_jsxs(PreviewSettingsProvider, { doc: doc, children: [_jsx("div", { className: "squisq-editor-header", children: _jsx(Toolbar, { showFiles: showFiles, onToggleFiles: !isCodeMode && filesToggleEnabled ? handleToggleFiles : undefined, slotLeft: toolbarSlotLeft, slotAfterActions: _jsxs(_Fragment, { children: [toolbarSlotAfterActions, !isCodeMode && isPreview && _jsx(PreviewToolbarControls, {})] }), slotRight: toolbarSlotRight, showPlayTab: showPlayTab }) }), _jsxs("div", { className: "squisq-editor-content", style: {
|
|
177
|
+
flex: autoGrow ? '1 1 auto' : 1,
|
|
178
|
+
overflowY: autoGrow ? 'auto' : 'hidden',
|
|
179
|
+
overflowX: 'hidden',
|
|
180
|
+
minHeight: 0,
|
|
181
|
+
position: 'relative',
|
|
182
|
+
display: 'flex',
|
|
183
|
+
}, children: [_jsxs("div", { style: {
|
|
184
|
+
flex: autoGrow ? '1 1 auto' : 1,
|
|
185
|
+
overflow: autoGrow ? 'visible' : 'hidden',
|
|
186
|
+
minHeight: 0,
|
|
187
|
+
position: 'relative',
|
|
188
|
+
}, children: [activeView === 'raw' && (_jsx(RawEditor, { theme: theme === 'dark' ? 'vs-dark' : 'vs', submitOnEnter: submitOnEnter, readOnly: readOnly })), !isCodeMode && activeView === 'wysiwyg' && (_jsx(WysiwygEditor, { submitOnEnter: submitOnEnter, placeholder: placeholder, readOnly: readOnly })), !isCodeMode && isPreview && _jsx(PreviewPanel, { basePath: basePath, container: container })] }), !isCodeMode && showFiles && (_jsx(MediaBin, { mediaProvider: mediaProvider, isDark: isDark, refreshKey: mediaRefreshKey, onMediaUploaded: insertMediaRef })), !isCodeMode && isDragging && (_jsx(DropZoneOverlay, { dragContentType: dragContentType, zoneProps: zoneProps, hasMediaProvider: mediaProvider !== null }))] }), showStatusBar && _jsx(StatusBar, {})] }), _jsx(TooltipLayer, {})] }));
|
|
105
189
|
}
|
|
106
190
|
//# sourceMappingURL=EditorShell.js.map
|
package/dist/EditorShell.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EditorShell.js","sourceRoot":"","sources":["../src/EditorShell.tsx"],"names":[],"mappings":";AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACzD,OAAO,
|
|
1
|
+
{"version":3,"file":"EditorShell.js","sourceRoot":"","sources":["../src/EditorShell.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImageNodeView.d.ts","sourceRoot":"","sources":["../src/ImageNodeView.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;
|
|
1
|
+
{"version":3,"file":"ImageNodeView.d.ts","sourceRoot":"","sources":["../src/ImageNodeView.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAkEH;;;GAGG;AACH,eAAO,MAAM,sBAAsB,kFAIjC,CAAC"}
|
package/dist/ImageNodeView.js
CHANGED
|
@@ -14,8 +14,9 @@ import Image from '@tiptap/extension-image';
|
|
|
14
14
|
import { useEditorContext } from './EditorContext';
|
|
15
15
|
function ImageComponent({ node }) {
|
|
16
16
|
const { src, alt, title } = node.attrs;
|
|
17
|
-
const { mediaProvider } = useEditorContext();
|
|
17
|
+
const { mediaProvider, imageDisplayMode } = useEditorContext();
|
|
18
18
|
const [resolvedSrc, setResolvedSrc] = useState(src);
|
|
19
|
+
const isThumbnail = imageDisplayMode === 'thumbnail';
|
|
19
20
|
const isRelative = src &&
|
|
20
21
|
!src.startsWith('blob:') &&
|
|
21
22
|
!src.startsWith('http') &&
|
|
@@ -38,7 +39,16 @@ function ImageComponent({ node }) {
|
|
|
38
39
|
cancelled = true;
|
|
39
40
|
};
|
|
40
41
|
}, [src, mediaProvider, isRelative]);
|
|
41
|
-
return (_jsx(NodeViewWrapper, { as: "figure", style: { margin: '0.5em 0' }, children: _jsx("img", { src: resolvedSrc, alt: alt || '', title: title || undefined,
|
|
42
|
+
return (_jsx(NodeViewWrapper, { as: "figure", style: { margin: '0.5em 0' }, children: _jsx("img", { src: resolvedSrc, alt: alt || '', title: title || undefined, className: isThumbnail ? 'squisq-image squisq-image--thumbnail' : 'squisq-image', style: isThumbnail
|
|
43
|
+
? {
|
|
44
|
+
maxWidth: '100px',
|
|
45
|
+
maxHeight: '100px',
|
|
46
|
+
width: 'auto',
|
|
47
|
+
height: 'auto',
|
|
48
|
+
objectFit: 'contain',
|
|
49
|
+
display: 'block',
|
|
50
|
+
}
|
|
51
|
+
: { maxWidth: '100%', height: 'auto', display: 'block' } }) }));
|
|
42
52
|
}
|
|
43
53
|
/**
|
|
44
54
|
* Image extension with a custom React NodeView that resolves URLs
|